package mobilesmil.activity;

import java.io.File;

import mobilesmil.activity.composer.ComposerActivity;
import mobilesmil.data.SmilDataSet;
import mobilesmil.data.SmilResource;
import mobilesmil.data.SmilVideoResource;
import mobilesmil.view.SmilView;
import mobilesmil.xml.parsing.SmilParser;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.SurfaceHolder.Callback;
import android.widget.FrameLayout;
import android.widget.MediaController;

public class PlayerActivity extends Activity implements Callback{
	private final int MENU_EDIT = 0;
	private final int MENU_STOP = 1;
	private final int MENU_OPEN = 2;
	private final int MENU_BACK_EDIT = 3;
	
	FrameLayout mFrameLayout;
	private SmilView mSmilView;
	private MediaController mMediaCon;
	private SmilDataSet mPlayDataSet;
	private boolean mFromBrowser;
	public SmilVideoResource mSmilVid;
	private boolean mSurfaceReady = false;
	
	private class DisplaySurfaceRunnable implements Runnable{
		private SurfaceView surf;
		private FrameLayout.LayoutParams mNewParams;
		
		public DisplaySurfaceRunnable(SurfaceView surf, FrameLayout.LayoutParams newParams){
			this.surf = surf;
			mNewParams = newParams;
		}
		
		@Override public void run(){
			if(surf != null){
				if(mNewParams == null){
					surf.setVisibility(View.INVISIBLE);
					surf.invalidate();
					Log.i("HideView", "Hide " + surf.toString());
				}
				else{
					FrameLayout.LayoutParams mVidParms = new FrameLayout.LayoutParams(surf.getWidth(), surf.getHeight());
					mVidParms.gravity = Gravity.TOP;
					mVidParms.topMargin = mNewParams.topMargin;
					mVidParms.leftMargin = mNewParams.leftMargin;
					surf.setLayoutParams(mVidParms);
					surf.invalidate();
					
					Log.i("HideView", "Show " + surf.toString());
				}
			}
		}
	}
	
	/**
	 * This method can be passed a view that needs to be set to View.INVISIBLE or View.VISIBLE.
	 * Visibility operations need to be ran on the UI thread, and this acts as a gateway to the
	 * UI thread.
	 * @param v	The view to alter
	 * @param toHide true will set View.INVISIBLE, false will set View.VISIBLE
	 */
	public synchronized void displaySurface(SurfaceView v, FrameLayout.LayoutParams newParams){
		DisplaySurfaceRunnable hvr = new DisplaySurfaceRunnable(v, newParams);
		runOnUiThread(hvr);
	}
	
	@Override protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		mFrameLayout = new FrameLayout(this);
		mFrameLayout.setWillNotDraw(true);
		FrameLayout.LayoutParams smilParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.FILL_PARENT);
		setContentView(mFrameLayout, smilParams);
		
		mSmilView = new SmilView(mFrameLayout.getContext(),null);
		mSmilView.setZOrderMediaOverlay(true);
		mSmilView.getHolder().addCallback(this);
		mSmilView.setLayoutParams(smilParams);
		mSmilView.setCallingActivity(this);
		mFrameLayout.addView(mSmilView);
		
		mMediaCon = new MediaController(this);
		mMediaCon.setMediaPlayer(mSmilPlayerInterface);
		mMediaCon.setEnabled(true);
		mMediaCon.setAnchorView(mFrameLayout);
		mMediaCon.setLayoutParams(smilParams);
		
		Intent in = getIntent();
		if(in.hasExtra(getString(R.string.playerTask))){
			try {
				String playTask = in.getExtras().getString(getString(R.string.playerTask));
				if(playTask.equals(getString(R.string.preview))){
					mFromBrowser = false;
					mPlayDataSet = ComposerActivity.getEditingDataSet();
					
					File tmpFile = new File(SmilResource.ROOT_PATH + mPlayDataSet.getFileName() + ".smil");
					if(tmpFile.exists())
						mPlayDataSet = SmilParser.getParsedDataSet(SmilResource.ROOT_PATH + mPlayDataSet.getFileName());
						
					loadAnyVideos();
					if(mSurfaceReady)
						mSmilView.playPlayer(mPlayDataSet);
				}
				else if(playTask.equals(getString(R.string.play))){
					mFromBrowser = true;
					String fileName = in.getStringExtra(getString(R.string.fileName));
					if(fileName != null){
						mPlayDataSet = SmilParser.getParsedDataSet(fileName);
						loadAnyVideos();
						if(mSurfaceReady)
							mSmilView.playPlayer(mPlayDataSet);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	private void loadAnyVideos(){
		//load surface views for all the videos in the smil
		synchronized(mSmilView){
			SurfaceView view;
			SmilVideoResource video = null;
			int startIndex = 0;
			int nextVideoIndex = mPlayDataSet.nextIndexOfType(SmilResource.TYPE_VIDEO, 0);
			while(nextVideoIndex != -1){
				System.gc();	//signal to garbage collect to help grant mediaplayer objects to video
				video = (SmilVideoResource) mPlayDataSet.getResourcesByBeginTime().get(nextVideoIndex);
				view = new SurfaceView(mFrameLayout.getContext());
				view.setDrawingCacheBackgroundColor(Color.TRANSPARENT);
				view = video.prepareVideo(view);
				mFrameLayout.addView(view);
				startIndex ++;
				nextVideoIndex = mPlayDataSet.nextIndexOfType(SmilResource.TYPE_VIDEO, nextVideoIndex + 1);
			}
			Log.d("LoadVideos", "" + startIndex + " videos loaded");
		}
	}
	
	@Override public boolean onTouchEvent(MotionEvent event) {
		mMediaCon.show();
		return super.onTouchEvent(event);
	}
	
	@Override public boolean onCreateOptionsMenu(Menu menu) {
		menu.add(0, MENU_OPEN, 0, "Open a SMIL").setIcon(android.R.drawable.ic_menu_gallery);
		
		return true;
	}

	@Override public boolean onPrepareOptionsMenu(Menu menu) {
		//add the stop button if playing
		if(mSmilView.getPlayState() > SmilView.STOPPED && menu.findItem(MENU_STOP) == null)
				menu.add(0, MENU_STOP, 1, "Stop SMIL").setIcon(android.R.drawable.ic_menu_close_clear_cancel);
		else if(mSmilView.getPlayState() <= SmilView.STOPPED && menu.findItem(MENU_STOP) != null)
			menu.removeItem(MENU_STOP);
		
		//add the appropriate eddit button
		if(mFromBrowser && menu.findItem(MENU_EDIT) == null)
			menu.add(0, MENU_EDIT, 2, "Edit This SMIL").setIcon(android.R.drawable.ic_menu_edit);
		
		if(!mFromBrowser && menu.findItem(MENU_BACK_EDIT) == null)
			menu.add(0, MENU_BACK_EDIT, 2, "Continue Edit").setIcon(android.R.drawable.ic_menu_edit);
			
		return true;
	}
	
	@Override public boolean onOptionsItemSelected(MenuItem item) {
		switch(item.getItemId()){
			case MENU_OPEN:
				Intent manager = new Intent(getApplicationContext(), FileBrowserActivity.class);
				manager.putExtra(getString(R.string.managerTask), "");
				startActivity(manager);
				return true;
			case MENU_STOP:
				mSmilView.stopPlayer();
				return true;
			case MENU_EDIT:
				Intent composer = new Intent(getApplicationContext(), ComposerActivity.class);
				composer.putExtra(getString(R.string.composerTask), getString(R.string.edit));
				composer.putExtra(getString(R.string.fileName), getIntent().getExtras().getString(getString(R.string.fileName)));
				startActivity(composer);
				return true;
			case MENU_BACK_EDIT:
				finish();
		}
		
		return true;
	}

	@Override protected void onPause() {
		super.onPause();
		finish();		//when this activity goes in the background finish it
	}
	
	@Override public void finish() {
		mSmilView.stopPlayer();	//ensure the player has been stopped if not already
		mMediaCon.hide();		//hide the controller so it isn't using resources that aren't there anymore
		System.gc();			//signal now would be a good time to garbage collect, to clean up any used mediaplayers
		super.finish();
	}

	private void restartPlayer(){
		startActivity(getIntent());
	}
	
	private void nextSmil(boolean forward){
		String fileName = getIntent().getStringExtra(getString(R.string.fileName));
		String nextFile = FileBrowserActivity.getFile(forward, fileName);
		getIntent().putExtra(getString(R.string.fileName), nextFile);
		startActivity(getIntent());
	}
	
	MediaController.MediaPlayerControl mSmilPlayerInterface = new MediaController.MediaPlayerControl() {
		
		@Override public void start() {
			if(mSmilView.getPlayState() == SmilView.STOPPED)
				mSmilView.playPlayer(mPlayDataSet);
			else if(mSmilView.getPlayState() == SmilView.PLAYED)
				restartPlayer();
			else if(mSmilView.getPlayState() == SmilView.PAUSED)
				mSmilView.resumePlayer();
		}
		
		@Override public void seekTo(int pos) {
			if(pos > 0)
				nextSmil(true);
			else
				nextSmil(false);
		}
		
		@Override public void pause() {
			mSmilView.pausePlayer();
		}
		
		@Override public boolean isPlaying() {
			if(mSmilView.getPlayState() == SmilView.PLAYING)
				return true;
			else
				return false;
		}
		
		@Override public int getDuration() {
			return mPlayDataSet.getLength()*1000;
		}
		
		@Override public int getCurrentPosition() {
			return mSmilView.getRuntime()*1000;
		}
		
		@Override public int getBufferPercentage() {
			return 100;
		}
		
		@Override public boolean canSeekForward() {
			return mFromBrowser;
		}
		
		@Override public boolean canSeekBackward() {
			return mFromBrowser;
		}
		
		@Override public boolean canPause() {
			return true;
		}
	};

	@Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}

	@Override public void surfaceCreated(SurfaceHolder holder) {
		mSurfaceReady = true;
		if(mPlayDataSet != null)
			mSmilView.playPlayer(mPlayDataSet);
		
	}

	@Override public void surfaceDestroyed(SurfaceHolder holder) {}
}